﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.ComponentModel;
using SqlSugar;
using Magic.Core.Entity;
using Namotion.Reflection;
using System.IO;
using ManagementTools.Service.Dto;
using Mapster;
using Yitter.IdGenerator;

namespace ManagementTools.Service
{
    internal class DicToEnumService
    {
        private SqlSugarClient mClient;
        public  string? ErrMsg { get; private set; }
      
        public DicToEnumService(SqlSugarClient client)
        {
            mClient = client;
            
        }

        public long InsertDictType(DicTypeXto dictType)
        {
            mClient.Deleteable<SysDictTypeDto>().Where(t => t.Code == dictType.Code).ExecuteCommand();//先删除已有数据
            var entity = dictType.Adapt<SysDictTypeDto>();

            entity.Id = YitIdHelper.NextId();
            
            entity.CreatedTime = mClient.GetDate();
            entity.CreatedUserName = "ManagementTool";
            var res= mClient.Insertable(entity).ExecuteReturnEntity();
            if(res==null)
            {
                ErrMsg = "插入数据失败";
                return 0;
            }
            else
            {
                return res.Id;
            }
            
        }
        public int InsertDictData(long typeId, IEnumerable<DicDataXto> datas)
        {
            int count = 0;
            mClient.BeginTran();
            try
            {
                foreach (var data in datas)
                {
                    mClient.Deleteable<SysDictData>().Where(d => d.TypeId == typeId && d.Value==data.Value).ExecuteCommand();//先删除已有数据
                    var entity = data.Adapt<SysDictData>();
                    entity.Id = YitIdHelper.NextId();
                    entity.TypeId = typeId;
                    entity.CreatedTime = mClient.GetDate();
                    entity.CreatedUserName = "ManagementTool";
                    count += mClient.Insertable(entity).ExecuteCommand();
                }
                mClient.CommitTran();
            }
            catch (Exception ex)
            {
                ErrMsg = ex.Message +"\r\n"+ ex.StackTrace;
                count = 0;
                mClient.RollbackTran();
            }

            return count;

        }
        /// <summary>
        /// 从数据库中查询字典值，并生成Enum文件
        /// 数据库字段与枚举的对应关系如下
        /// value --> Item.Name
        /// code --> Item.Value (如果能解释成整数)
        /// remark --> Item Discription标签
        /// </summary>
        /// <param name="dicTypeName">字典名称，对应sys_dict_type中的Code字段</param>
        /// <param name="targPath">输出路径，文件名为targPath\{dicTypeName(Camel风格)}.cs</param>
        /// <param name="namespace">命名空间</param>
        /// <remarks>之所以讲dicTypeName对应到Code字段，是为了用方便用显示字典中文名称，再加上系统的code用的是ascii字符串，可以有一致性</remarks>
        public bool DictionaryToEnum(string dicTypeName, string targPath, string @namespace="Magic.Application.Enums")
        {
            var dicType = mClient.Queryable<SysDictTypeDto>().Where(t => t.Code == dicTypeName).First();
            if(dicType == null)
            {
                ErrMsg = "未查询到Code为" + dicTypeName + "的字典名称";
                return false;
            }
            var enumType=UnderScoresStyleToCamelStyle(dicTypeName);
             var values = mClient.Queryable<SysDictData>().Where(d => d.TypeId == dicType.Id).ToList();
            if(values.Any())
            {
                StringBuilder sb=new StringBuilder();
                sb.AppendLine("using System;                                ");
                sb.AppendLine("using System.Collections.Generic;            ");
                sb.AppendLine("using System.ComponentModel;                 ");
                sb.AppendLine("using System.Linq;                           ");
                sb.AppendLine("using System.Text;                           ");
                sb.AppendLine("using System.Threading.Tasks;                ");
                sb.AppendLine("                                             ");
                sb.AppendLine($"namespace {@namespace}            ");
                sb.AppendLine("{                                            ");
                sb.AppendLine("    /// <summary>                            ");
                sb.AppendLine($"    /// {dicType.Name}                             ");
                sb.AppendLine("    /// </summary>                           ");
                sb.AppendLine($"    /// <remarks>{dicType.Remark}</remarks>");
                sb.AppendLine($"    [Description(\"{dicTypeName}\")]      ");
                sb.AppendLine($"    public enum {enumType}            ");
                sb.AppendLine("    {                                        ");
                foreach (var value in values)
                {
                    sb.AppendLine("        /// <summary>                        ");
                    sb.AppendLine($"        /// {value.Remark}                           ");
                    sb.AppendLine("        /// </summary>                       ");
                    sb.AppendLine($"        /// <remarks>{value.Remark}</remarks>        ");
                    sb.AppendLine($"        [Description(\"{value.Remark}\")]              ");
                    if(int.TryParse(value.Code,out int code))
                    {
                        sb.AppendLine($"        {value.Value} = {code},                    ");
                    }
                    else
                    {
                        sb.AppendLine($"        {value.Value},                        ");
                    }
                    
                }
                sb.AppendLine("    }                                        ");
                sb.AppendLine("}                                            ");
                try
                {
                    File.WriteAllText(Path.Combine(targPath, enumType + ".cs"), sb.ToString());
                }
                catch (Exception ex)
                {
                    ErrMsg = ex.Message;
                    return false;
                }
            }
            else
            {
                ErrMsg = "未查询到Code为" + dicTypeName + "的字典数据";
                return false;
            }
            return true;    
        }
        /// <summary>
        /// 下划线风格转换为驼峰风格(C#风格)
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static string UnderScoresStyleToCamelStyle(string src)
        {
            var segs = src.Split('_', StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < segs.Length; i++)
            {
                var seg = segs[i];
                if (!string.IsNullOrEmpty(seg))
                {
                    segs[i] = seg.Substring(0, 1).ToUpper() + seg.Substring(1);
                }
            }
            var camel = string.Join("", segs);
            return camel;
        }
        /// <summary>
        /// 雪花ID需要登录才可以生成
        /// </summary>
        /// <param name="enumType"></param>
        public  void EnumToDictionary(Type enumType)
        {
            string name = enumType.Name;
 
             var attr = enumType.GetCustomAttribute(typeof(DescriptionAttribute));
            if (attr != null)
            {
                name = ((DescriptionAttribute)attr).Description;
            }
           
            var dicType= mClient.Queryable<SysDictTypeDto>().Where(t => t.Code == name).First();
            if(dicType==null)
            {
                
                string summary=enumType.GetXmlDocsSummary();
                string remark = enumType.GetXmlDocsRemarks();
                if (string.IsNullOrEmpty(summary)) summary = name;
                if (string.IsNullOrEmpty(remark)) remark = name;
                dicType = new SysDictTypeDto()
                {
                    Code = name,
                    Name=summary,
                    Remark=remark
                };
                dicType = mClient.Insertable(dicType).CallEntityMethod(m=>m.Create()).ExecuteReturnEntity();
               
            }
            if (dicType.Id > 0)
            {
                int code = 0;

                foreach (var item in enumType.GetFields())
                {
                    string summary = item.GetXmlDocsSummary();
                    string remark = item.GetXmlDocsRemarks();
                    var dicData = new SysDictData
                    {
                        TypeId = dicType.Id,
                        Value = summary,
                        Code = (code).ToString(),
                        Sort = 100 + code++,
                        Remark = remark
                    };
                    mClient.Insertable(dicData).ExecuteCommand();
                }
            }
            
        }
       
        // 获取方法
        private string GetDescriptionByEnum(Enum enumValue)
        {
            string value = enumValue.ToString();
            System.Reflection.FieldInfo field = enumValue.GetType().GetField(value);
            object[] objs = field.GetCustomAttributes(typeof(DescriptionAttribute), false);    //获取描述属性
            if (objs.Length == 0)    //当描述属性没有时，直接返回名称
                return value;
            DescriptionAttribute descriptionAttribute = (DescriptionAttribute)objs[0];
            return descriptionAttribute.Description;
        }

    }
}
